﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using Reviewer.Business;
using Reviewer.Entities;
using Reviewer.Entities.Services;
using System.Collections.ObjectModel;

/// <summary>
/// Summary description for GameUriHandler
/// </summary>
public static class UriHandler
{
    private static readonly object syncObject = new object();

    public static Dictionary<string, Guid> GameDictionary
    {
        get
        {
            Dictionary<string, Guid> gamesDictionary = HttpContext.Current.Cache["GamesUriDictionary"] as Dictionary<string, Guid>;
            if (gamesDictionary == null || HttpContext.Current.Request.Url.PathAndQuery.IndexOf("forceRefresh=doit") > 0)
            {
                lock (syncObject)
                {
                    gamesDictionary = HttpContext.Current.Cache["GamesUriDictionary"] as Dictionary<string, Guid>;
                    if (gamesDictionary == null)
                    {
                        gamesDictionary = new Dictionary<string, Guid>();
                        using (IGameService gameService = ServiceFactory.GameService)
                        {
                            Game[] allGames = gameService.GetAll().GroupBy(t => t.GameId).Select(t => t.First()).ToArray();
                            foreach (Game game in allGames)
                            {
                                try
                                {
                                    gamesDictionary.Add(UrlUtillity.NormalizeString(game.Title), game.GameId);
                                }
                                catch (ArgumentException e)
                                {
                                    if (!e.Message.Equals("An item with the same key has already been added."))
                                        throw e;
                                }
                                catch (Exception error)
                                {
                                    System.Diagnostics.Debug.WriteLine(error.ToString());
                                }
                            }
                        }
                        HttpContext.Current.Cache.Add("GamesUriDictionary", gamesDictionary, null, DateTime.Now.AddMinutes(30), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.AboveNormal, null);
                    }
                }
            }
            return gamesDictionary;
        }
    }

    public static void ClearGamesDirectory()
    {
        HttpContext.Current.Cache.Remove("GamesUriDictionary");
    }

    public static Dictionary<string, Guid> NewsDictionary
    {
        get
        {
            Dictionary<string, Guid> newsDictionary = HttpContext.Current.Cache["NewsUriDictionary"] as Dictionary<string, Guid>;
            if (newsDictionary == null)
            {
                lock (syncObject)
                {
                    newsDictionary = HttpContext.Current.Cache["NewsUriDictionary"] as Dictionary<string, Guid>;
                    if (newsDictionary == null)
                    {
                        try
                        {
                            newsDictionary = new Dictionary<string, Guid>();
                            using (INewsService newsService = ServiceFactory.NewsService)
                            {
                                News[] allNews = newsService.GetAll().ToArray();
                                foreach (News news in allNews)
                                {
                                    string normalized = UrlUtillity.NormalizeString(news.Title);
                                    if (!newsDictionary.ContainsKey(normalized))
                                    {
                                        newsDictionary.Add(UrlUtillity.NormalizeString(news.Title), news.NewsId);
                                    }
                                }
                            }
                            HttpContext.Current.Cache.Add("NewsUriDictionary", newsDictionary, null, DateTime.Now.AddMinutes(30), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.AboveNormal, null);
                        }
                        catch (Exception error)
                        {
                            Console.WriteLine(error.ToString());
                        }
                    }
                }
            }
            return newsDictionary;
        }
    }

    public static void ClearNewsDirectory()
    {
        HttpContext.Current.Cache.Remove("NewsUriDictionary");
    }

    public static bool ReWrite(HttpContext context)
    {
        try
        {
            string[] uriParts = context.Request.Url.AbsolutePath.Substring(context.Request.ApplicationPath == "" ? 1 : context.Request.ApplicationPath.Length).Split('/');

            switch (uriParts[0].ToUpperInvariant())
            {
                case "SPIL":
                    string gameTitle;
                    if (uriParts[uriParts.Length - 1].IndexOf(".") > -1)
                        gameTitle = context.Server.UrlDecode(uriParts[uriParts.Length - 1].Substring(0, uriParts[uriParts.Length - 1].LastIndexOf(".")));
                    else
                    {
                        gameTitle = context.Server.UrlDecode(uriParts[uriParts.Length - 1]);
                        gameTitle = gameTitle.Trim().Replace(" ", "-");
                    }

                    string format = uriParts[uriParts.Length - 2];
                    if (!String.IsNullOrEmpty(gameTitle))
                    {
                        Guid gameId = GameDictionary.First(t => t.Key.ToUpperInvariant().Equals(gameTitle.ToUpperInvariant(), StringComparison.Ordinal)).Value;
                        using (IMetadataService<Format> service = ServiceFactory.GetMetadataService<Format>())
                        {
                            Format f = service.GetAll().FirstOrDefault(t => UrlUtillity.NormalizeString(t.Name).ToUpperInvariant().Equals(format.ToUpperInvariant(), StringComparison.Ordinal));

                            if (context.Request.Url.Query.Contains("&r="))
                                context.Response.Redirect(VirtualPathUtility.ToAbsolute("/Spil.aspx") + "?GameId=" + gameId.ToString() + "&format=" + f.Id.ToString());
                            else
                                context.Server.Transfer(VirtualPathUtility.ToAbsolute("/Spil.aspx") + "?GameId=" + gameId.ToString() + "&format=" + f.Id.ToString());
                            return true;
                        }
                    }
                    break;
                case "NYHED":
                    string newsTitle = context.Server.UrlDecode(uriParts[uriParts.Length - 1].Substring(0, uriParts[uriParts.Length - 1].LastIndexOf(".")));
                    if (!String.IsNullOrEmpty(newsTitle))
                    {
                        Guid newsId = NewsDictionary.First(t => t.Key.ToUpperInvariant().Equals(newsTitle.ToUpperInvariant(), StringComparison.Ordinal)).Value;

                        context.RewritePath(VirtualPathUtility.ToAbsolute("/Nyhed.aspx") + "?NewsId=" + newsId.ToString());
                        return true;
                    }
                    break;
                case "ANMELDELSE":
                    string reviewGameTitle = context.Server.UrlDecode(uriParts[uriParts.Length - 1].Substring(0, uriParts[uriParts.Length - 1].LastIndexOf(".")));
                    string reviewGameFormat = uriParts[uriParts.Length - 2];
                    if (!String.IsNullOrEmpty(reviewGameTitle))
                    {
                        Guid gameId = GameDictionary.First(t => t.Key.ToUpperInvariant().Equals(reviewGameTitle.ToUpperInvariant(), StringComparison.Ordinal)).Value;
                        using (IMetadataService<Format> service = ServiceFactory.GetMetadataService<Format>())
                        using (IGameService gameService = ServiceFactory.GameService)
                        using (IReviewService reviewService = ServiceFactory.ReviewService)
                        {
                            Format formatItem = service.GetAll().FirstOrDefault(t => UrlUtillity.NormalizeString(t.Name).ToUpperInvariant().Equals(reviewGameFormat.ToUpperInvariant(), StringComparison.Ordinal));

                            if (formatItem != null)
                            {
                                Game[] games = gameService.GetBy(gameId);
                                Game gameItem = games.FirstOrDefault(t => t.Format.Equals(formatItem.Id));
                                if (gameItem != null)
                                {
                                    Collection<Review> review = reviewService.FindByGameId(gameItem.Id);
                                    if (review != null && review.Count > 0)
                                    {
                                        context.RewritePath(VirtualPathUtility.ToAbsolute("/Anmeldelse.aspx") + "?ReviewId=" + review[0].Id.ToString());
                                        return true;
                                    }
                                }
                            }
                        }
                    }
                    break;
                case "VIDEO":
                    if (!File.Exists(context.Server.MapPath(context.Request.Url.AbsolutePath)))
                    {
                        string gameVideoId = uriParts[uriParts.Length - 1].Substring(uriParts[uriParts.Length - 1].IndexOf("-") + 1);
                        gameVideoId = gameVideoId.Substring(0, gameVideoId.IndexOf("."));
                        context.RewritePath(VirtualPathUtility.ToAbsolute("/Videoplayer.aspx") + "?Id=" + gameVideoId);
                    }
                    break;
                case "INFO":
                    if (!File.Exists(context.Server.MapPath(context.Request.Url.AbsolutePath)))
                    {
                        context.RewritePath(VirtualPathUtility.ToAbsolute("/InfoPage.aspx") + "?PageName=" + uriParts[1].Substring(0, uriParts[1].LastIndexOf(".")));
                    }
                    break;
                default:
                    if (context.Request.Url.AbsolutePath.ToUpperInvariant().EndsWith("PNG"))
                    {
                        if (!File.Exists(context.Server.MapPath(context.Request.Url.AbsolutePath)))
                        {
                            context.RewritePath(VirtualPathUtility.ToAbsolute("/images/MainLogo.png"));
                        }
                        else
                        {
                            context.Response.ExpiresAbsolute = DateTime.Today.AddDays(10);
                        }
                    }
                    else if (context.Request.Url.AbsolutePath.ToUpperInvariant().EndsWith("JPG"))
                    {
                        if (!File.Exists(context.Server.MapPath(context.Request.Url.AbsolutePath)))
                        {
                            context.RewritePath(VirtualPathUtility.ToAbsolute("/images/logo.jpg"));
                        }
                        else
                        {
                            context.Response.ExpiresAbsolute = DateTime.Today.AddDays(10);
                        }
                    }
                    break;
            }

            if (uriParts.Length == 1 && !File.Exists(context.Server.MapPath(context.Request.Url.AbsolutePath)))
            {
                UI.URL handler = new UI.URL();
                handler.ProcessRequest(context);
            }
        }
        catch (Exception error)
        {
            //context.Response.Redirect(VirtualPathUtility.ToAbsolute("~/500.aspx"));
            //return;
            System.Diagnostics.Trace.TraceError(error.ToString());
        }

        return false;
    }
}
